---@class Utility : Object
local Utility = {}

--变革技
Utility.Reform = "HQ.Reform"

--合纵技
Utility.VerticalAlliance = "HQ.VerticalAlliance"

--连横技
Utility.HorizontalAlliance = "HQ.HorizontalAlliance"

------------------------------------------------------------------------------------------------------
---爆发
---@param player ServerPlayer
---@return integer[]
Utility.burst = function (player)
  local room = player.room
  local info = room:getBanner("hanqing__burst") or {}
  local n = info.n or 2
  local cards = {}
  while true do
    local will_break = false
    if #room.draw_pile < n then
      will_break = true
    end
    local ids = room:getNCards(n)
    table.insertTableIfNeed(cards, ids)
    room:turnOverCardsFromDrawPile(player, ids, "hanqing__burst")
    if #room.draw_pile == 0 then
      room:shuffleDrawPile()
      will_break = true
    end
    if not will_break then
      will_break = Fk:getCardById(room.draw_pile[1]).color == Card.Red
    end
    if will_break then
      break
    end
  end
  if player.dead then
    room:cleanProcessingArea(cards)
    return cards
  else
    local black = table.filter(cards, function (id)
      return Fk:getCardById(id).color == Card.Black
    end)
    local fire = table.find(cards, function (id)
      local card = Fk:getCardById(id)
      return card.is_damage_card and table.contains({"fire__slash", "fire_attack", "burning_camps"}, card.name)
    end)
    if #black > 0 then
      local targets = table.filter(room.alive_players, function (p)
        return not p:isNude()
      end)
      if table.contains(targets, player) and
        not table.find(player:getCardIds("he"), function (id)
          return not player:prohibitDiscard(id)
        end) then
        table.removeOne(targets, player)
      end
      local min = math.min(#black, #targets)
      if #targets == 0 then
        min = #black
        room:askToCards(player, {
          min_num = 1,
          max_num = 1,
          include_equip = false,
          skill_name = "hanqing__burst",
          pattern = "false",
          prompt = "#hanqing__burst-black:::"..min,
          cancelable = true,
        })
      else
        local tos = room:askToChoosePlayers(player, {
          min_num = 1,
          max_num = min,
          targets = targets,
          skill_name = "hanqing__burst",
          prompt = "#hanqing__burst-black:::"..min,
          cancelable = true,
        })
        if #tos > 0 then
          room:sortByAction(tos)
          for _, p in ipairs(tos) do
            if p == player then
              room:askToDiscard(player, {
                min_num = 1,
                max_num = 1,
                include_equip = true,
                skill_name = "hanqing__burst",
                cancelable = false,
              })
            elseif not p.dead and not p:isNude() then
              local card = room:askToChooseCard(player, {
                target = p,
                flag = "he",
                skill_name = "hanqing__burst",
              })
              room:throwCard(card, "hanqing__burst", p, player)
            end
            if player.dead then
              room:cleanProcessingArea(cards)
              return cards
            end
          end
        end
      end
    end
    local red = table.filter(cards, function (id)
      return Fk:getCardById(id).color == Card.Red and room:getCardArea(id) == Card.Processing
    end)
    if #red > 0 then
      local card = room:askToChooseCard(player, {
        target = player,
        flag = { card_data = {{ "hanqing__burst", red }} },
        skill_name = "hanqing__burst",
        prompt = "#hanqing__burst-red",
      })
      if not room:askToUseRealCard(player, {
        pattern = {card},
        skill_name = "hanqing__burst",
        prompt = "#hanqing__burst-use",
        extra_data = {
          bypass_times = true,
          extraUse = true,
          expand_pile = {card},
        },
        cancelable = not table.contains(player:getTableMark("hanqing__cuipo"), "$Hand"),
      }) then
        room:moveCardTo(card, Card.PlayerHand, player, fk.ReasonJustMove, "hanqing__burst", nil, true, player)
      end
      if player.dead then
        room:cleanProcessingArea(cards)
        return cards
      end
    end
    if fire then
      local to = room:askToChoosePlayers(player, {
        min_num = 1,
        max_num = 1,
        targets = room.alive_players,
        skill_name = "hanqing__burst",
        prompt = "#hanqing__burst-fire",
        cancelable = false,
      })[1]
      room:damage{
        from = player,
        to = to,
        damage = 1,
        skillName = "hanqing__burst",
      }
    end
  end
  room:cleanProcessingArea(cards)
  return cards
end

Fk:loadTranslationTable{
  ["hanqing__burst"] = "爆发",
  [":hanqing__burst"] = "亮出牌堆顶两张牌并重复，直到牌堆顶牌不为红色或牌堆切洗。“爆发”结束后，你根据亮出牌种类依次执以下效果："..
  "黑色牌，弃置至多等量名角色各一张牌；红色牌，获得或使用其中一张；火属性牌，分配1点火焰伤害。",

  ["#hanqing__burst-black"] = "爆发：弃置至多%arg名角色各一张牌",
  ["#hanqing__burst-red"] = "爆发：获得或使用其中一张牌",
  ["#hanqing__burst-use"] = "爆发：使用这张牌，或点“取消”获得之",
  ["#hanqing__burst-fire"] = "爆发：对一名角色造成1点火焰伤害",
}

------------------------------------------------------------------------------------------------------
---纵横捭阖
---合纵/连横状态：处于合纵状态的角色视为拥有所有其他同状态角色“合纵技”的“捭阖：”描述前的技能效果；
---处于连横状态的角色视为拥有所有其他同状态角色“连横技”的“捭阖：”描述前的技能效果；
---重置武将牌或对同状态其他角色造成伤害将退出合纵/连横状态；合纵和连横状态不共存。

--- HQAllianceChangedData 数据
---@class HQAllianceChangedDataSpec
---@field public n integer @ 数量

---@class Utility.HQAllianceChangedData: HQAllianceChangedDataSpec, TriggerData
Utility.HQAllianceChangedData = TriggerData:subclass("HQAllianceChangedData")

--- TriggerEvent
---@class Utility.HQAllianceChangedTriggerEvent: TriggerEvent
---@field public data Utility.HQAllianceChangedData
Utility.HQAllianceChangedTriggerEvent = TriggerEvent:subclass("HQAllianceChangedEvent")

--- 纵横状态变化前
---@class Utility.BeforeHQAllianceChanged: Utility.HQAllianceChangedTriggerEvent
Utility.BeforeHQAllianceChanged = Utility.HQAllianceChangedTriggerEvent:subclass("fk.BeforeHQAllianceChanged")

--- 纵横状态变化后
---@class Utility.HQAllianceChanged: Utility.HQAllianceChangedTriggerEvent
Utility.HQAllianceChanged = Utility.HQAllianceChangedTriggerEvent:subclass("fk.HQAllianceChanged")

---@alias HQAllianceChangedTrigFunc fun(self: TriggerSkill, event: Utility.HQAllianceChangedTriggerEvent,
---  target: ServerPlayer, player: ServerPlayer, data: Utility.HQAllianceChangedData):any

---@class SkillSkeleton
---@field public addEffect fun(self: SkillSkeleton, key: Utility.HQAllianceChangedTriggerEvent,
---  data: TrigSkelSpec<HQAllianceChangedTrigFunc>, attr: TrigSkelAttribute?): SkillSkeleton

---获得角色的纵横状态
---@param player Player
---@return "vertical" | "horizontal" | ""
Utility.getAlliance = function (player)
  if player:getMark("@@hanqing__vertical_alliance") > 0 then
    return "vertical"
  elseif player:getMark("@@hanqing__horizontal_alliance") > 0 then
    return "horizontal"
  end
  return ""
end

---设置纵横状态
---@param player ServerPlayer
---@param status "horizontal" | "vertical" | ""
Utility.setAlliance = function (player, status, data)
  local room = player.room
  assert(status == "vertical" or status == "horizontal" or status == "", "Invalid status")

  if data == nil then
    data = {
      who = player,
      reason = room.logic:getCurrentSkillName() or "game_rule",
    }
  end

  if Utility.getAlliance(player) ~= status then
    room.logic:trigger(Utility.BeforeHQAllianceChanged, player, data)
    if data.prevented then
      return false
    end
    if Utility.getAlliance(player) ~= status then
      if status == "vertical" then
        room:setPlayerMark(player, "@@hanqing__vertical_alliance", 1)
        room:setPlayerMark(player, "@@hanqing__horizontal_alliance", 0)
        room:sendLog{
          type = "#ChainStateChange",
          from = player.id,
          arg = "@@hanqing__vertical_alliance",
        }
      elseif status == "horizontal" then
        room:setPlayerMark(player, "@@hanqing__vertical_alliance", 0)
        room:setPlayerMark(player, "@@hanqing__horizontal_alliance", 1)
        room:sendLog{
          type = "#ChainStateChange",
          from = player.id,
          arg = "@@hanqing__horizontal_alliance",
        }
      elseif status == "" then
        room:setPlayerMark(player, "@@hanqing__vertical_alliance", 0)
        room:setPlayerMark(player, "@@hanqing__horizontal_alliance", 0)
      end
      room.logic:trigger(Utility.HQAllianceChanged, player, data)
    end
  end
end

Fk:loadTranslationTable{
  ["#hanqingAllianceChange"] = "%from 进入了 %arg 状态",
  ["@@hanqing__vertical_alliance"] = "合纵",
  ["@@hanqing__horizontal_alliance"] = "连横",
  ["hanqing__alliance_href"] = "处于合纵/连横状态的角色视为拥有所有其他同状态角色“合纵/连横技”的“捭阖：”描述前的技能效果；<br>"..
  "重置武将牌或对同状态其他角色造成伤害将退出合纵/连横状态；<br>合纵和连横状态不共存",
  ["hanqing__alliance_skill"] = "技能标签带有“合纵/连横技”的角色可以将多目标锦囊牌转化为<a href=':hanqing__vh_alliance'>【纵横捭阖】</a>；<br>"..
  "处于合纵状态的角色视为拥有所有其他同状态角色“合纵技”的“捭阖：”描述前的技能效果；"..
  "处于连横状态的角色视为拥有所有其他同状态角色“连横技”的“捭阖：”描述前的技能效果",
}


return Utility
